home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / mail / listserv / utils / mmdfcatmail.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-01  |  7.3 KB  |  289 lines

  1. /*
  2.  *                              mmdfcatmail.c
  3.  *
  4.  *  Due to the behavior of MMDF (at least on SCO Unix), we can't use
  5.  * listserv's /usr/server/catmail program within an aliased pipe.  MMDF strips
  6.  * the first "From  " line in pipes, which listserv requires.  It would
  7.  * probably be best if listserv always used the From: or Sender: rfc822 header.
  8.  *
  9.  * This program is a frontend to catmail.  It reads ahead in a mail steam and
  10.  * picks the sender's address from the rfc822 header and assembles a fake
  11.  * "From addr date" line and sends the whole mess to catmail.  All command line
  12.  * arguments are passed directly to catmail.
  13.  *
  14.  *  To use this facility with MMDF, add lines such as this to your
  15.  * /usr/mmdf/table/alias.list:
  16.  *
  17.  *  listserv: server|/usr/server/mmdfcatmail -r -f
  18.  *  somelist: server|/usr/server/mmdfcatmail -L SOMELIST -f
  19.  *
  20.  * Note that your /usr/mmdf/mmdftailor file must have the "trusted" keyword
  21.  * in the ALIAS entry for the alias.list file or pipes will not work:
  22.  *
  23.  *    ALIAS     table=lalias,   nobypass,       trusted 
  24.  *
  25.  * Here is the don't sue me copyright:
  26.  *
  27.  * Copyright 1993 Mark Diekhans (markd@grizzly.com)
  28.  * Permission to use, copy, modify, and distribute this software and its
  29.  * documentation for any purpose and without fee is hereby granted, provided
  30.  * that the above copyright notice appear in all copies.  Mark Diekhans makes
  31.  * no representations about the suitability of this software for any purpose.
  32.  * It is provided "as is" without express or implied warranty.
  33.  *
  34.  * PORT: Ported by Tasos Kotsikonas (tasos@cs.bu.edu):
  35.  * - CATMAIL is defined in ansi/start.h or nonansi/start.h
  36.  * - used wait3() for certain systems instead of waitpid()
  37.  * - if WAIT3_NEEDS_UNION is defined then use a union status variable
  38.  * - STDIN_FILENO replaced by fileno(stdin)
  39.  * - WIFEXITED and WEXITSTATUS adjusted according to the system
  40.  */
  41.  
  42.  
  43. #include <stdio.h>
  44. #ifndef unknown_port
  45. # include <unistd.h>
  46. #endif
  47. #include <string.h>
  48. #include <ctype.h>
  49. #include <errno.h>
  50. #ifdef unknown_port
  51. extern int errno;
  52. #endif
  53. #include <sys/types.h>
  54. #include <sys/wait.h>
  55.  
  56. #include "defs.h"
  57. #include "struct.h"
  58. #include "global.h"
  59. #ifdef __STDC__
  60. # include "ansi/start.h"
  61. #else
  62. # include "nonansi/start.h"
  63. #endif
  64. #ifndef WAIT3_NEEDS_UNION
  65. # if defined (sequent) || defined (stardent) || defined (stellar) || \
  66.   defined (titan) || defined (unknown_port)
  67. #  ifdef WEXITSTATUS
  68. #   undef WEXITSTATUS
  69. #  endif
  70. #  ifdef WIFEXITED
  71. #   undef WIFEXITED
  72. #  endif
  73. # endif
  74. #endif
  75.  
  76. #ifndef WEXITSTATUS
  77. # define  WEXITSTATUS(stat)     ((int)(((stat)>>8)&0377))
  78. #endif
  79. # ifndef WIFEXITED
  80. #  define WIFEXITED(stat)       (((int)((stat)&0377))==0)
  81. # endif
  82.  
  83. BOOLEAN tty_echo = FALSE; /* -e option off */
  84. FILE *report      = NULL; /* Progress report to the administrator */
  85.  
  86. extern void extract_address (char *);
  87.  
  88. /*
  89.  * Maximum number of lines to read looking for "From:" or "Sender:".
  90.  */
  91. #define MAX_HEADER_LINES  2048
  92.  
  93. /*
  94.  * Type used to save header fields in memory.  Also structure used to
  95.  * keep a list of these header lines.
  96.  */
  97. typedef struct strEntry_t {
  98.     struct strEntry_t *next;
  99.     char               line [1];  /* MUST BE LAST FIELD. */
  100. } strEntry_t;
  101.  
  102. typedef struct {
  103.     strEntry_t  *head;
  104.     strEntry_t  *tail;
  105. } strList_t;
  106.  
  107. /*
  108.  * Save a line away in a dynamically allocated structure and added that
  109.  * structure to a list.
  110.  */
  111.  
  112. void
  113. SaveLine (const char  *line,
  114.           strList_t   *list)
  115. {
  116.     strEntry_t *entry;
  117.  
  118.     entry = (strEntry_t *) malloc (sizeof (strEntry_t) + (strlen (line)));
  119.     strcpy (entry->line, line);
  120.     entry->next = NULL;
  121.  
  122.     if (list->tail == NULL) {
  123.         list->head = entry;
  124.     } else {
  125.         list->tail->next = entry;
  126.     }
  127.     list->tail = entry;
  128. }
  129.  
  130. /*
  131.  * Start the catmail process.  
  132.  */
  133. pid_t
  134. StartCatmail (const char **argv,
  135.               FILE       **toPipe)
  136. {
  137.     int    pipefds [2];
  138.     pid_t  pid;
  139.  
  140.     *toPipe = NULL;
  141.  
  142.     if (pipe (pipefds) == 0) {
  143.         *toPipe = fdopen (pipefds [1], "w");
  144.     }
  145.     if (*toPipe == NULL) {
  146.         fprintf (stderr, "open of pipe failed: %s", strerror (errno));
  147.         exit (1);
  148.     }
  149.  
  150.     pid = fork ();
  151.     if (pid < 0) {
  152.         fprintf (stderr, "fork failed: %s", strerror (errno));
  153.         exit (1);
  154.     }
  155.     if (pid > 0) {
  156.         close (pipefds [0]);
  157.         return pid;
  158.     }
  159.  
  160.     close (pipefds [1]);
  161.     close (fileno (stdin));
  162.     if (dup2 (pipefds [0], fileno (stdin)) < 0) {
  163.         fprintf (stderr, "dup to stdin failed: %s", strerror (errno));
  164.         exit (1);
  165.     }
  166.  
  167.     argv [0] = strrchr (CATMAIL, '/');
  168.     if (argv [0] == NULL)
  169.         argv [0] = CATMAIL;
  170.     execv (CATMAIL, argv);
  171.     
  172.     fprintf (stderr, "exec of %s failed: %s", CATMAIL, strerror (errno));
  173.     exit (1);
  174. }
  175.  
  176. /*
  177.  * Do actual work of copying stdin catmail process, filling in the missing
  178.  * "From address Date" line.
  179.  */
  180. main (int          argc,
  181.       const char **argv)
  182. {
  183.     strList_t    headerList;
  184.     strEntry_t  *entry;
  185.     char         line [MAX_LINE + 1];
  186.     char         fromAddress [MAX_LINE];
  187.     char         date [MAX_LINE];
  188.     int          linesRead = 0;
  189. #ifdef WAIT3_NEEDS_UNION
  190.     union wait     waitStat;
  191. #else
  192.     int         waitStat;
  193. #endif
  194.     pid_t        pid;
  195.     FILE        *toPipe;
  196.  
  197.     headerList.head = NULL;
  198.     headerList.tail = NULL;
  199.     fromAddress [0] = '\0';
  200.     date [0] = '\0';
  201.  
  202.     /*
  203.      * Search for the minimum headers we need and save away lines for later
  204.      * output.
  205.      */
  206.     while (! ((fromAddress [0] != '\0') && (date [0] != '\0'))) {
  207.         if (fgets (line, MAX_LINE, stdin) == NULL)
  208.             break;
  209.  
  210.         SaveLine (line, &headerList);
  211.  
  212.         if (strncmp (line, "From:", 5) == 0) {
  213.             strcpy (fromAddress, line + 5); 
  214.             extract_address (fromAddress);
  215.             continue;
  216.         }
  217.         if (strncmp (line, "Sender:", 6) == 0) {
  218.             strcpy (fromAddress, line + 6); 
  219.             extract_address (fromAddress);
  220.             continue;
  221.         }
  222.         if (strncmp (line, "Date:", 5) == 0) {
  223.             strcpy (date, line + 6); 
  224.             continue;
  225.         }
  226.         linesRead++;
  227.         if (linesRead > MAX_HEADER_LINES)
  228.             break;
  229.     }
  230.     if (fromAddress [0] == '\0') {
  231.         fprintf (stderr, "No \"From:\" or \"Sender:\" header found\n");
  232.         exit (1);
  233.     }
  234.     if (date [0] == '\0') {
  235.         fprintf (stderr, "No \"date:\" header found\n");
  236.         exit (1);
  237.     }
  238.  
  239.     pid = StartCatmail (argv, &toPipe);
  240.  
  241.     /*
  242.      * Output our madeup from line. (date has "\n").
  243.      */
  244.     fprintf (toPipe, "From %s %s", fromAddress, date);
  245.  
  246.     entry = headerList.head;
  247.     while (entry != NULL) {
  248.         fputs (entry->line, toPipe);
  249.         entry = entry->next;
  250.     }
  251.  
  252.     while (fgets (line, MAX_LINE, stdin) != NULL)
  253.         fputs (line, toPipe);
  254.  
  255.     fclose (toPipe);
  256.  
  257. #if defined (sequent) || defined (stardent) || defined (stellar) || \
  258.  defined (titan) || defined (unknown_port)
  259.     do {
  260.     } while ((pid = wait3 (&waitStat, WNOHANG, NULL)));
  261.     if (pid < 0) {
  262.     fprintf (stderr, "wait3 failed: %s", strerror (errno));
  263.         exit (1);
  264.     }
  265. #else
  266.     if (waitpid (pid, &waitStat, 0) < 0) {
  267.         fprintf (stderr, "waitpid failed: %s", strerror (errno));
  268.         exit (1);
  269.     }
  270. #endif
  271.  
  272.     if (WIFEXITED (waitStat))
  273.         exit (WEXITSTATUS (waitStat));
  274.  
  275.     fprintf (stderr, "%s terminated for unknown reasons\n", CATMAIL);
  276.     exit (1);
  277.  
  278. }
  279.  
  280. /*
  281.  * The library needs this guy.
  282.  */
  283. int
  284. gexit (int exitcode)
  285. {
  286.     exit (exitcode);
  287. }
  288.  
  289.